package com.taobao.txc.sample;

import com.taobao.txc.client.aop.TxcClientInitDoneEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.jdbc.core.JdbcTemplate;

@SpringBootApplication
@EnableFeignClients
public class Application implements ApplicationListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);

    public static long ACCOUNT_A_ID = 0L;

    public static long ACCOUNT_B_ID = 0L;

    @Autowired
    private BizService bizService;

    @Autowired
    private JdbcTemplate jdbcTemplateA;

    @Autowired
    private JdbcTemplate jdbcTemplateB;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    private void initData() {
        // 随机生成帐户 ID
        ACCOUNT_A_ID = System.currentTimeMillis();
        ACCOUNT_B_ID = System.currentTimeMillis();
        // 初始化 A B 帐户各 10000
        jdbcTemplateA.update("truncate user_money_a");
        jdbcTemplateA.update("insert into user_money_a(id, money) values(?, 10000)", ACCOUNT_A_ID);
        jdbcTemplateB.update("truncate user_money_b");
        jdbcTemplateB.update("insert into user_money_b(id, money) values(?, 10000)", ACCOUNT_B_ID);
    }

    private void run() throws Exception {
        initData();

        int balanceA = jdbcTemplateA.queryForObject("select money from user_money_a where id = ?", java.lang.Integer.class, ACCOUNT_A_ID);
        int balanceB = jdbcTemplateB.queryForObject("select money from user_money_b where id = ?", java.lang.Integer.class, ACCOUNT_B_ID);
        LOGGER.info("Before transfer! A: " + balanceA + "   B: " + balanceB + "   total：" + (balanceA + balanceB));
        LOGGER.info("--------------------------------------------------------------------------------------------");

        int transferCount = 0;
        int transferMoneyCount = 0;
        for (int i = 1; i <= 50; ++i) {
            LOGGER.info("Transfer[" + i + "] begins ...");
            try {
                int money = 300;
                bizService.doTransfer(money);
                transferCount++;
                transferMoneyCount += money;
                LOGGER.info("Transfer[" + i + "] is done! ");
            } catch (Exception e) {
                LOGGER.info("Transfer[" + i + "] failed since " + e.getMessage() + ". Money is rolled back.");
            } finally {
                LOGGER.info("--------------------------------------------------------------------------------------------");
            }
        }
        LOGGER.info("Finally, " + transferCount + " transactions was done with " + transferMoneyCount);
    }

    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if (applicationEvent instanceof TxcClientInitDoneEvent) {
            try {
                run();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}
